package com.jinzhi.common.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {


    private static final int[] dayArray = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    private static SimpleDateFormat sdf = new SimpleDateFormat();

    public static synchronized Calendar getCalendar() {
        return GregorianCalendar.getInstance();
    }

    public static synchronized String getDateMilliFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateMilliFormat(cal);
    }

    public static synchronized String getDateMilliFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd HH:mm:ss,SSS";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateMilliFormat(Date date) {
        String pattern = "yyyy-MM-dd HH:mm:ss,SSS";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarMilliFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss,SSS";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateMilliFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss,SSS";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateSecondFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateSecondFormat(cal);
    }

    public static synchronized String getDateSecondFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateSecondFormat(Date date) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarSecondFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateSecondFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateMinuteFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateMinuteFormat(cal);
    }

    public static synchronized String getDateMinuteFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd HH:mm";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateMinuteFormat(Date date) {
        String pattern = "yyyy-MM-dd HH:mm";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarMinuteFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateMinuteFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm";
        return parseDateFormat(strDate, pattern);
    }

    public static String getDate(String patten) {
        SimpleDateFormat sf = new SimpleDateFormat(patten, Locale.US);
        return sf.format(new Date());
    }

    public static synchronized String getDateDayFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateDayFormat(cal);
    }

    public static synchronized String getDateDayFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateDayFormat(Date date) {
        String pattern = "yyyy-MM-dd";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarDayFormat(String strDate) {
        String pattern = "yyyy-MM-dd";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateDayFormat(String strDate) {
        String pattern = "yyyy-MM-dd";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateFileFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateFileFormat(cal);
    }

    public static synchronized String getDateFileFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd_HH-mm-ss";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateFileFormat(Date date) {
        String pattern = "yyyy-MM-dd_HH-mm-ss";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarFileFormat(String strDate) {
        String pattern = "yyyy-MM-dd_HH-mm-ss";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateFileFormat(String strDate) {
        String pattern = "yyyy-MM-dd_HH-mm-ss";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateW3CFormat() {
        Calendar cal = Calendar.getInstance();
        return getDateW3CFormat(cal);
    }

    public static synchronized String getDateW3CFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateW3CFormat(Date date) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarW3CFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateW3CFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateFormat(Calendar cal) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(cal, pattern);
    }

    public static synchronized String getDateFormat(Date date) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return getDateFormat(date, pattern);
    }

    public static synchronized Calendar parseCalendarFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseCalendarFormat(strDate, pattern);
    }

    public static synchronized Date parseDateFormat(String strDate) {
        String pattern = "yyyy-MM-dd HH:mm:ss";
        return parseDateFormat(strDate, pattern);
    }

    public static synchronized String getDateFormat(Calendar cal, String pattern) {
        return getDateFormat(cal.getTime(), pattern);
    }

    public static synchronized String getDateFormat(Date date, String pattern) {
        synchronized (sdf) {
            String str = null;
            sdf.applyPattern(pattern);
            str = sdf.format(date);
            return str;
        }
    }

    public static synchronized Calendar parseCalendarFormat(String strDate, String pattern) {
        synchronized (sdf) {
            Calendar cal = null;
            sdf.applyPattern(pattern);
            try {
                sdf.parse(strDate);
                cal = sdf.getCalendar();
            } catch (Exception e) {
            }

            return cal;
        }
    }

    public static synchronized Date parseDateFormat(String strDate, String pattern) {
        synchronized (sdf) {
            Date date = null;
            sdf.applyPattern(pattern);
            try {
                date = sdf.parse(strDate);
            } catch (Exception e) {
            }

            return date;
        }
    }

    public static synchronized int getLastDayOfMonth(int month) {
        if ((month < 1) || (month > 12)) {
            return -1;
        }
        int retn = 0;
        if (month == 2) {
            if (isLeapYear()) {
                retn = 29;
            } else {
                retn = dayArray[(month - 1)];
            }

        } else {
            retn = dayArray[(month - 1)];
        }
        return retn;
    }

    public static synchronized int getLastDayOfMonth(int year, int month) {
        if ((month < 1) || (month > 12)) {
            return -1;
        }
        int retn = 0;
        if (month == 2) {
            if (isLeapYear(year)) {
                retn = 29;
            } else {
                retn = dayArray[(month - 1)];
            }

        } else {
            retn = dayArray[(month - 1)];
        }
        return retn;
    }

    public static synchronized boolean isLeapYear() {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(1);
        return isLeapYear(year);
    }

    public static synchronized boolean isLeapYear(int year) {
        if (year % 400 == 0)
            return true;
        if (year % 4 == 0) {
            if (year % 100 == 0)
                return false;
            return true;
        }
        return false;
    }

    public static synchronized boolean isLeapYear(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        int year = gc.get(1);
        return isLeapYear(year);
    }

    public static synchronized boolean isLeapYear(Calendar gc) {
        int year = gc.get(1);
        return isLeapYear(year);
    }

    public static synchronized Date getPreviousWeekDay(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return getPreviousWeekDay(gc);
    }

    public static synchronized Date getPreviousWeekDay(Calendar gc) {
        switch (gc.get(7)) {
            case 2:
                gc.add(5, -3);
                break;
            case 1:
                gc.add(5, -2);
                break;
            default:
                gc.add(5, -1);
        }

        return gc.getTime();
    }

    public static synchronized Date getNextWeekDay(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        switch (gc.get(7)) {
            case 6:
                gc.add(5, 3);
                break;
            case 7:
                gc.add(5, 2);
                break;
            default:
                gc.add(5, 1);
        }

        return gc.getTime();
    }

    public static synchronized Calendar getNextWeekDay(Calendar gc) {
        switch (gc.get(7)) {
            case 6:
                gc.add(5, 3);
                break;
            case 7:
                gc.add(5, 2);
                break;
            default:
                gc.add(5, 1);
        }

        return gc;
    }

    public static synchronized Date getLastDayOfNextMonth(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.setTime(getNextMonth(gc.getTime()));
        gc.setTime(getLastDayOfMonth(gc.getTime()));
        return gc.getTime();
    }

    public static synchronized Date getLastDayOfNextWeek(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.setTime(getNextWeek(gc.getTime()));
        gc.setTime(getLastDayOfWeek(gc.getTime()));
        return gc.getTime();
    }

    public static synchronized Date getFirstDayOfNextMonth(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.setTime(getNextMonth(gc.getTime()));
        gc.setTime(getFirstDayOfMonth(gc.getTime()));
        return gc.getTime();
    }

    public static synchronized Calendar getFirstDayOfNextMonth(Calendar gc) {
        gc.setTime(getNextMonth(gc.getTime()));
        gc.setTime(getFirstDayOfMonth(gc.getTime()));
        return gc;
    }

    public static synchronized Date getFirstDayOfNextWeek(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.setTime(getNextWeek(gc.getTime()));
        gc.setTime(getFirstDayOfWeek(gc.getTime()));
        return gc.getTime();
    }

    public static synchronized Calendar getFirstDayOfNextWeek(Calendar gc) {
        gc.setTime(getNextWeek(gc.getTime()));
        gc.setTime(getFirstDayOfWeek(gc.getTime()));
        return gc;
    }

    public static synchronized Date getNextMonth(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.add(2, 1);
        return gc.getTime();
    }

    public static synchronized Calendar getNextMonth(Calendar gc) {
        gc.add(2, 1);
        return gc;
    }

    public static synchronized Date getNextDay(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.add(5, 1);
        return gc.getTime();
    }

    public static synchronized Calendar getNextDay(Calendar gc) {
        gc.add(5, 1);
        return gc;
    }

    public static synchronized Date getNextWeek(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.add(5, 7);
        return gc.getTime();
    }

    public static synchronized Calendar getNextWeek(Calendar gc) {
        gc.add(5, 7);
        return gc;
    }

    public static synchronized Date getLastDayOfWeek(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        switch (gc.get(7)) {
            case 1:
                gc.add(5, 6);
                break;
            case 2:
                gc.add(5, 5);
                break;
            case 3:
                gc.add(5, 4);
                break;
            case 4:
                gc.add(5, 3);
                break;
            case 5:
                gc.add(5, 2);
                break;
            case 6:
                gc.add(5, 1);
                break;
            case 7:
                gc.add(5, 0);
        }

        return gc.getTime();
    }

    public static synchronized Date getFirstDayOfWeek(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        switch (gc.get(7)) {
            case 1:
                gc.add(5, 0);
                break;
            case 2:
                gc.add(5, -1);
                break;
            case 3:
                gc.add(5, -2);
                break;
            case 4:
                gc.add(5, -3);
                break;
            case 5:
                gc.add(5, -4);
                break;
            case 6:
                gc.add(5, -5);
                break;
            case 7:
                gc.add(5, -6);
        }

        return gc.getTime();
    }

    public static synchronized Calendar getFirstDayOfWeek(Calendar gc) {
        switch (gc.get(7)) {
            case 1:
                gc.add(5, 0);
                break;
            case 2:
                gc.add(5, -1);
                break;
            case 3:
                gc.add(5, -2);
                break;
            case 4:
                gc.add(5, -3);
                break;
            case 5:
                gc.add(5, -4);
                break;
            case 6:
                gc.add(5, -5);
                break;
            case 7:
                gc.add(5, -6);
        }

        return gc;
    }

    public static synchronized Date getLastDayOfMonth(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        switch (gc.get(2)) {
            case 0:
                gc.set(5, 31);
                break;
            case 1:
                gc.set(5, 28);
                break;
            case 2:
                gc.set(5, 31);
                break;
            case 3:
                gc.set(5, 30);
                break;
            case 4:
                gc.set(5, 31);
                break;
            case 5:
                gc.set(5, 30);
                break;
            case 6:
                gc.set(5, 31);
                break;
            case 7:
                gc.set(5, 31);
                break;
            case 8:
                gc.set(5, 30);
                break;
            case 9:
                gc.set(5, 31);
                break;
            case 10:
                gc.set(5, 30);
                break;
            case 11:
                gc.set(5, 31);
        }


        if ((gc.get(2) == 1) && (isLeapYear(gc.get(1)))) {
            gc.set(5, 29);
        }
        return gc.getTime();
    }

    public static synchronized Calendar getLastDayOfMonth(Calendar gc) {
        switch (gc.get(2)) {
            case 0:
                gc.set(5, 31);
                break;
            case 1:
                gc.set(5, 28);
                break;
            case 2:
                gc.set(5, 31);
                break;
            case 3:
                gc.set(5, 30);
                break;
            case 4:
                gc.set(5, 31);
                break;
            case 5:
                gc.set(5, 30);
                break;
            case 6:
                gc.set(5, 31);
                break;
            case 7:
                gc.set(5, 31);
                break;
            case 8:
                gc.set(5, 30);
                break;
            case 9:
                gc.set(5, 31);
                break;
            case 10:
                gc.set(5, 30);
                break;
            case 11:
                gc.set(5, 31);
        }


        if ((gc.get(2) == 1) && (isLeapYear(gc.get(1)))) {
            gc.set(5, 29);
        }
        return gc;
    }

    public static synchronized Date getFirstDayOfMonth(Date date) {
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        gc.set(5, 1);
        return gc.getTime();
    }

    public static synchronized Calendar getFirstDayOfMonth(Calendar gc) {
        gc.set(5, 1);
        return gc;
    }

    public static synchronized String toOraString(Date theDate, boolean hasTime) {
        DateFormat theFormat;

        if (hasTime) {
            theFormat = getOraDateTimeFormat();
        } else {
            theFormat = getOraDateFormat();
        }
        return toString(theDate, theFormat);
    }

    public static synchronized String toString(Date theDate, boolean hasTime) {
        DateFormat theFormat;

        if (hasTime) {
            theFormat = getDateTimeFormat();
        } else {
            theFormat = getDateFormat();
        }
        return toString(theDate, theFormat);
    }

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");

    private static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("MM/dd/yyyy HH:mm");

    private static final SimpleDateFormat DATE_TIME_EXTENDED_FORMAT = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    private static final SimpleDateFormat ORA_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

    private static final SimpleDateFormat ORA_DATE_TIME_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");

    private static final SimpleDateFormat ORA_DATE_TIME_EXTENDED_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");

    public static synchronized DateFormat getDateFormat() {
        SimpleDateFormat theDateFormat = (SimpleDateFormat) DATE_FORMAT.clone();

        theDateFormat.setLenient(false);
        return theDateFormat;
    }

    public static synchronized DateFormat getDateTimeFormat() {
        SimpleDateFormat theDateTimeFormat = (SimpleDateFormat) DATE_TIME_FORMAT.clone();

        theDateTimeFormat.setLenient(false);
        return theDateTimeFormat;
    }

    public static synchronized DateFormat getOraDateFormat() {
        SimpleDateFormat theDateFormat = (SimpleDateFormat) ORA_DATE_FORMAT.clone();

        theDateFormat.setLenient(false);
        return theDateFormat;
    }

    public static synchronized DateFormat getOraDateTimeFormat() {
        SimpleDateFormat theDateTimeFormat = (SimpleDateFormat) ORA_DATE_TIME_FORMAT.clone();

        theDateTimeFormat.setLenient(false);
        return theDateTimeFormat;
    }

    public static synchronized String toString(Date theDate, DateFormat theDateFormat) {
        if (theDate == null)
            return "";
        return theDateFormat.format(theDate);
    }

    public static String getDate(Date date, String patten) {
        SimpleDateFormat sf = new SimpleDateFormat(patten);
        return sf.format(date);
    }

    public static Date getDate(String dateStr, String patten) throws ParseException {
        if (dateStr == null)
            return null;
        SimpleDateFormat sf = new SimpleDateFormat(patten);
        return sf.parse(dateStr);
    }

    public static String getRomNum() {
        double ranNum = Math.random();
        int i = (int) (ranNum * 1000000.0D);
        return String.valueOf(i);
    }

    public static String getDateStr(String dateStr, String old_pattern, String new_pattern) {
        String sDate = "";
        try {
            sDate = getDate(getDate(dateStr, old_pattern), new_pattern);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sDate;
    }

    public static String getRomNum(int several) {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < several; i++) {
            sb.append(random.nextInt(9));
        }
        return sb.toString();
    }

    public static String randomNoRepeat(int several) {
        int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        int length = array.length;
        if (several > length) {
            several = length;
        }
        Random rand = new Random();
        for (int i = length; i > 1; i--) {
            int index = rand.nextInt(i);
            int tmp = array[index];
            array[index] = array[(i - 1)];
            array[(i - 1)] = tmp;
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < several; i++) {
            sb.append(array[i]);
        }
        return sb.toString();
    }

    public static long getTimesnight() {
        Calendar cal = Calendar.getInstance();
        cal.set(11, 24);
        cal.set(13, 0);
        cal.set(12, 0);
        cal.set(14, 0);
        return cal.getTimeInMillis() / 1000L;
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param nowTime 当前时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    public static long getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        long mins = (day * 24 * 60) + (hour * 60) + min;
        return mins;
    }

    public static void main(String[] args) {

        String timeString = "2020-05-27 15:30:00";
        String timeString1 = "2020-05-28 17:00:00";

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//注意月份是MM
        Date date = null;
        Date date1 = null;
        try {
            date = simpleDateFormat.parse(timeString);
            date1 = simpleDateFormat.parse(timeString1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(getDatePoor(date1,date));   //Mon Sep 02 00:00:00 CST 2019
//        System.out.println(simpleDateFormat.format(date));  //2019-09-02
//
//        System.out.println(getDateStr(timeString, "yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss"));
    }
}
